package ipc;


import ipc.Node;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;
import java.util.Vector;

import rddl.ActionGenerator;
import rddl.EvalException;
import rddl.RDDL.LCONST;
import rddl.RDDL.PVARIABLE_DEF;
import rddl.RDDL.PVARIABLE_STATE_DEF;
import rddl.RDDL.PVAR_NAME;
import rddl.RDDL.PVAR_INST_DEF;

import java.util.Random;

/**
 * Enhanced UCT agent that can be run as normal UCT or a modified version of UCT
 * based on input parameters.
 */
public final class SpuddAgent<S extends State, A> extends Agent<S, A> {

    private myDD _spudd;
    private String spudd_file;
    
	private String inst_name;
	private int horizon;    

    public SpuddAgent(String inst_name, int hor, Simulator<S, A> sim) {
    	this.simulator_ = sim.copy();
    	this.horizon = hor;
		this.inst_name = inst_name;
        name_ = "UCT";
    }

    @Override
    public A selectAction(S state, long timeout, int time) {
    	long tim = System.currentTimeMillis();
    	simulator_.setState(state);
    	simulator_.setTime(time);
    	List<A> legals = simulator_.getLegalActions();
    	
    	System.out.println("time = " + time);
    	
    	int hor = horizon-time-1;
    	
    	System.out.println("hor = " + hor);
		tim = System.currentTimeMillis()-tim;    	
		timeout -= tim;
		
    	while( !SPUDDer.isFinished(inst_name, hor) && timeout > tim ){
    		tim = System.currentTimeMillis();
    		SPUDDer.updateDD(inst_name, (long)(0.3d*timeout));
    		tim = System.currentTimeMillis()-tim;
    		timeout -= tim;
    	}
    System.out.println(SPUDDer.isFinished(inst_name, hor));
    
    System.out.println(SPUDDer.getLastSeen(inst_name));
    	
    	double maxQ = Double.NEGATIVE_INFINITY;
    	A maxA = null;
    	
    	for( A thisA : legals ){
    		double thisQ = computeQ(thisA, simulator_, true, hor);
    		if( thisQ > maxQ ){
    			maxQ = thisQ;
    			maxA = thisA;
    		}
    		
//    		System.out.println(thisA + " " + thisQ);
    	}
//    	try {
//			System.in.read();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
    	return maxA;
    }
	
    private double computeQ(A thisA, Simulator<S, A> simulator_, boolean valuepol, int hor) {
    	double avgQ = 0;
    	for( int i = 0 ; i < 10; ++i ){
    		Simulator<S, A> clone = simulator_.copy();
    		clone.takeAction(thisA);
    		try{
    			avgQ += (Double)Query.query(clone, valuepol, hor, inst_name);
    		}catch(Exception e){}
    	}
    	return avgQ / 10;
    	
	}

}
